package com.zhaungjie.base.utils.ExcelUtil.style;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.style.AbstractCellStyleStrategy;
import com.zhaungjie.base.utils.ExcelUtil.constant.StyleConstant;
import com.zhaungjie.base.utils.ExcelUtil.style.annotation.ExcelCellStyle;
import com.zhaungjie.base.utils.ExcelUtil.style.matcher.CellStyleMatcher;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Field;
import java.util.Objects;

public class CustomCellStyleStrategy extends AbstractCellStyleStrategy {
    /**
     * 设置表头样式
     */
    @Override
    protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
        // 设置表头单元格样式
    }

    @Override
    protected void setContentCellStyle(CellWriteHandlerContext context) {
        ExcelContentProperty excelContentProperty = context.getExcelContentProperty();
        Field field = excelContentProperty.getField();
        Object fieldValue = context.getOriginalValue();
        ExcelCellStyle[] excelCellStyleAnnotations = field.getAnnotationsByType(ExcelCellStyle.class);
        for (ExcelCellStyle excelCellStyleAnnotation : excelCellStyleAnnotations) {
            // 判断条件是否满足
            String conditionForSpEL = excelCellStyleAnnotation.condition();
            Class<CellStyleMatcher> cellStyleMatcherClass = excelCellStyleAnnotation.complexCondition();
            // 当声明SpELCondition了且声明不满足，该注解上的样式不会应用
            if (conditionForSpEL != null && isNotPassSpELCondition(conditionForSpEL, field,fieldValue)) {
                continue;
            }
            // 当声明ComplexCondition了且声明不满足，该注解上的样式不会应用
            // `cellStyleMatcherClass != CellStyleMatcher.class` 如果相等表示没有定义值，应是其实现类
            if (cellStyleMatcherClass != null && cellStyleMatcherClass != CellStyleMatcher.class && isNotPassComplexCondition(cellStyleMatcherClass, field,fieldValue)) {
                continue;
            }
            // conditionForSpEL条件与cellStyleMatcherClass的满足条件，则设置单元格样式
            applyCellStyle(excelCellStyleAnnotation,context);
        }

    }

    private void applyCellStyle(ExcelCellStyle excelCellStyleAnnotation, CellWriteHandlerContext context) {
        Cell cell = context.getCell();
        Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
        CellStyle cellStyle = workbook.createCellStyle();
        if (excelCellStyleAnnotation.fillBackgroundColor() != StyleConstant.COLOR_VALUE_UNDEFINED) {
            cellStyle.setFillBackgroundColor(excelCellStyleAnnotation.fillBackgroundColor());
        }
        if (excelCellStyleAnnotation.fontColor() != StyleConstant.COLOR_VALUE_UNDEFINED) {
            Font writeFont = workbook.createFont();
            writeFont.setColor(excelCellStyleAnnotation.fontColor());
            // fontWeight annotation field handler
            writeFont.setBold(excelCellStyleAnnotation.fontWeight());
            cellStyle.setFont(writeFont);
        }
        cell.setCellStyle(cellStyle);
        // 不写下面样式不生效！
        context.getFirstCellData().setWriteCellStyle(null);
    }

    private boolean isNotPassComplexCondition(Class<CellStyleMatcher> cellStyleMatcherClass, Field field, Object fieldValue) {
        try {
            CellStyleMatcher cellStyleMatcher = cellStyleMatcherClass.newInstance();
            return !cellStyleMatcher.match(fieldValue);
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 是否通过spEL condition
     *
     * @param spELCondition spEL条件
     * @param field         field对象
     * @param fieldValue    字段值
     * @return boolean
     */
    private boolean isNotPassSpELCondition(String spELCondition, Field field, Object fieldValue) {
        EvaluationContext spELContext = new StandardEvaluationContext();
        spELContext.setVariable(field.getName(), fieldValue);
        ExpressionParser parser = new SpelExpressionParser();

        Expression expression = parser.parseExpression(spELCondition);
        // spELValue是否为false
        return Objects.equals(expression.getValue(spELContext, Boolean.class),false);
    }
}